package mini.reanimate;

import static bogus.core.BogusCore.egl;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;

import audio.Audio;
import audio.Clip;
import owg.util.Calc;
import owg.util.euclidian.Compass;
import owg.util.opengl.ColorF;
import world.Sound;
import graphics.Shape;
import hubol.Hubol;
import hubol.Shake;
import hubol.Sprite;

public class Flame extends Screen{
	private final int x = -96, y = -52;
	private final int bogusX = 800 + x, bogusY = 460 + y;
	private final int shootX = bogusX - 239 + 78, shootY = bogusY - 136 + 16;
	
	private final float SCALE = 1.025f;
	private final FLayer BACK = new FLayer(new Layer("closeup", 0), new Layer("flameback")), BACKTREE = new FLayer(new Layer("closeup", 1), new Layer("flamebtree")), FRONTTREE = new FLayer(new Layer("closeup", 2), new Layer("flameftree")), FRONTGRASS = new FLayer(new Layer("closeup", 3), new Layer("flamefront"));
	private final FLayer HEAD1 = new FLayer(new Layer("flamehead1")), HEAD2 = new FLayer(new Layer("flamehead2")), HEAD3 = new FLayer(new Layer("flamehead3")); 
	private ArrayList<FLayer> activeLayers = new ArrayList<FLayer>();
	
	private final Sprite name = new Sprite("borgusname"), back = new Sprite("iamback"), suck = new Sprite("yousuck");
	
	private ArrayList<Shoot> shoots = new ArrayList<Shoot>();
	
	private int timer = 0;
	private boolean flame = false, shadow = true;

	private final Clip softFlame = Audio.getClip("softflame"), loudFlame = Audio.getClip("loudflame"), catchFire = Audio.getClip("catchfire"), music = Audio.getClip("inflame"), cool = Audio.getClip("endwrite");
	private double loudVolume = 0, loudPitch = 2;
	
	private Borgus borgus;
	
	private boolean fuck = false, DONOT = false;
	private int record;
	
	private final ColorF FLAME = new ColorF(Color.decode("#F72E00"));
	
	private float nameProg = 0;
	
	private Clip drone = Audio.getClip("drone");
	private double droneVolume = 0;
	private int iamback = 0, yousuck = 0;
	
	private Shake[] shake = Shake.shake(6);
	
	public Flame() {
		super(12, "headstone", "flameshootback", "flameshootnext", "flameshootfront", "borgus");
		sprite[0].setOrigin(Compass.NORTHWEST);
		HEAD1.setNorthwest();
		HEAD2.setNorthwest();
		HEAD3.setNorthwest();
		layer(BACK);
		layer(BACKTREE);
		layer(FRONTTREE);
		layer(FRONTGRASS);
		
		//
		//BACK.burn();
	}
	
	public void layer(FLayer f){
		activeLayers.add(f);
	}
	
	public void render(FLayer f, Shake s){
		if (activeLayers.contains(f))
			f.render(s);
	}
	
	private void catchFire(){
		Hubol.playPitched(catchFire);
	}

	@Override
	public void step() {
		timer++;
		if (timer == 45){
			flame = true;
			softFlame.loop();
			loudFlame.loop();
			music.loop();
			softFlame.setPosition(null, 1);
		}
		if (timer >= 45){
			loudFlame.setPosition(null, loudVolume);
			loudFlame.setSpeed(null, loudPitch);
			
			final double goalV = 1;
			loudVolume = Calc.approach(loudVolume, goalV, 10);
			loudPitch = Calc.approach(loudPitch, 1, 4.5);
			
			softFlame.setPosition(null, 1 - ((timer - 45) / 145.0));
			if (timer > 190)
				softFlame.stop();
		}
		if (timer == 55){
			catchFire();
			layer(HEAD2);
		}
		else if (timer == 70){
			catchFire();
			layer(HEAD3);
		}
		else if (timer == 85){
			catchFire();
			layer(HEAD1);
		}
		else if (timer == 100){
			FRONTGRASS.burn();
			catchFire();
		}
		else if (timer == 130){
			shadow = false;
			BACK.burn();
			catchFire();
		}
		else if (timer == 160){
			FRONTTREE.burn();
			catchFire();
		}
		else if (timer == 190){
			BACKTREE.burn();
			catchFire();
		}
		else if (timer == 220){
			flame = false;
			cool.play();
		}
		else if (timer == 280){
			Reanimate.me.BOGUS.flameDance(1200);
		}
		else if (timer == 1005){
			Reanimate.me.HUD = false;
			Reanimate.me.BOGUS.setScale(0.4f);
			Reanimate.me.BOGUS.setPosition(635, 396);
			Reanimate.me.BOGUS.xscale = -1;
			loudFlame.stop();
			fuck = true;
		}
		if (record != 0){
			if (timer == record + 45){
				Audio.getClip("crash").setPosition(null, .5);
				borgus = new Borgus(233, 396);
				drone.loop();
			}
			
			if (timer == record + 105 + 60){
				iamback++;
				Sound.play("i");
				Sound.playPitched("crash");
			}
			
			if (timer == record + 150 + 60){
				iamback++;
				Sound.play("am");
				Sound.playPitched("crash");
			}
			
			if (timer == record + 255){
				iamback++;
				Sound.play("back");
				Sound.playPitched("crash");
				Reanimate.me.BOGUS.jump();
			}
			
			if (timer == record + 315){
				yousuck++;
				Sound.play("you");
				Sound.playPitched("crash");
			}
			
			if (timer == record + 360){
				yousuck++;
				Sound.play("suck");
				Sound.playPitched("crash");
				Reanimate.me.BOGUS.jump();
			}
			
			if (timer == record + 1080)
				Reanimate.me.completeMinigame();
			
			if (droneVolume < .95)
				droneVolume += .003;
			drone.setPosition(null, droneVolume);
		}
		if (timer >= 1005 && (timer - 1005) % 45 == 0 && !DONOT){
			Reanimate.me.BOGUS.jump();
		}
		
		if (flame)
			shoots.add(new Shoot(shootX + Calc.rangedRandom(.1), shootY + Calc.rangedRandom(.1)));
		for (Shoot s : shoots)
			s.step();
		for (int i=0; i<shoots.size(); i++){
			if (shoots.get(i).dead)
				shoots.remove(i);
		}
		for (FLayer f : activeLayers)
			f.step();
		
		if (borgus != null)
			borgus.step();
	}

	@Override
	public void enter() {
		Reanimate.me.BOGUS.setScale(0.74074074074074074074074074074074f);
		Reanimate.me.BOGUS.setPosition(bogusX, bogusY);
		Reanimate.me.BOGUS.flame();
		Reanimate.me.BUSY = true;
		Reanimate.me.BOGUS.toCancel = false;
		
		cool.play();
		Reanimate.me.stop();
	}
	
	@Override
	public void bogusLand() {
		if (nameProg < 1){
			nameProg = (float)Math.min(1, (nameProg + .05) * 1.1);
			Audio.getClip("name").setPosition(null, .4 + (.6 * nameProg));
			Sound.playPitched("name");
			
			if (nameProg >= 1){
				Sound.play("crash");
				DONOT = true;
				record = timer;
				nameProg = 2;
				Audio.getClip("inflame").stop();
			}
		}
	}

	@Override
	public void leave() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean background() {
		if (!fuck){
			render(BACK, s[9]);
			render(BACKTREE, s[10]);
			render(FRONTTREE, s[11]);
			for (int i=0; i<5; i++)
				sprite[0].render(i, s[i].x + x, s[i].y + y);
			render(HEAD1, s[6]);
			render(HEAD2, s[7]);
			for (Shoot s : shoots)
				s.render(1);
			for (Shoot s : shoots)
				s.render(2);
			for (Shoot s : shoots)
				s.render(3);
			render(HEAD3, s[8]);
		}
		else{
			egl.setColor(FLAME);
			egl.setAlpha(1);
			Shape.drawRectangle(0, 0, 864, 486);
			egl.setColor(ColorF.WHITE);
			
			name.render(0, 432 + shake[0].x, 243 + shake[0].y, nameProg * 4, nameProg * 4, 0, ColorF.WHITE);
			
			for (int i=0; i<iamback; i++)
				back.render(i, 432 + shake[i + 1].x, 70 + shake[i + 1].y, 3.4188034188034188034188034188034f, 3.4188034188034188034188034188034f, 0, ColorF.WHITE);
			
			for (int i=0; i<yousuck; i++)
				suck.render(i, 432 + shake[i + 4].x, 416 + shake[i + 4].y, 3.4188034188034188034188034188034f, 3.4188034188034188034188034188034f, 0, ColorF.WHITE);
		}
		
		return shadow;
	}

	@Override
	public void foreground() {
		if (!fuck)
			render(FRONTGRASS, s[5]);
		if (borgus != null)
			borgus.render();
	}
	
	private class Shoot{
		private final double SIZE = .5;
		
		private double x, y;
		private double hsp, vsp;
		
		private double scale = 0;
		private double image = 0;
		
		private double goal = .8 + Calc.random(.4);
		private double life = 90 + Calc.random(40);
		
		public boolean dead = false;
		
		public Shoot(double x, double y){
			this.x = x;
			this.y = y;
			hsp = -3.9 - Calc.random(.4);
			vsp = 3.9 + Calc.random(.4);
			hsp *= 2;
			vsp *= 2;
			scale = Calc.random(.5);
			if (Calc.random() > .9){
				hsp += Calc.rangedRandom(2);
				vsp = Calc.random(8);
				scale *= .01;
				goal *= .4;
			}
		}
		
		public void step(){
			x += hsp;
			y += vsp;
			
			if (y > 370){
				vsp = Calc.approach(vsp, 0, 5);
				hsp = Calc.approach(hsp, 0, 25);
				scale = Calc.approach(scale, 0, 50);
			}
			else
				scale = Calc.approach(scale, goal, 10);
			
			if (image < 2)
				image += .2;
			else if (Calc.random() > .5)
				image = 2 + Calc.random(2);
			
			life--;
			if (life <= 0)
				dead = true;
		}
		
		public void render(int flame){
			sprite[flame].render(2 + Calc.random(2), (float)(x + Calc.rangedRandom(.1)), (float)(y + Calc.rangedRandom(.1) - (8 * scale)), (float)(scale * SIZE), (float)(scale * SIZE * 2), 0, ColorF.WHITE);
			//sprite[flame].render(image, (float)(x + Calc.rangedRandom(.1)), (float)(y + Calc.rangedRandom(.1)), (float)(scale * SIZE), (float)(scale * SIZE), angle, ColorF.WHITE);
		}
	}
	
	private class FLayer{
		private Point render = new Point(432, 243);
		private Layer burning;
		private Layer visible;
		
		public FLayer(Layer normal, Layer burning){
			this.burning = burning;
			visible = normal;
		}
		
		public FLayer(Layer visible){
			this.visible = visible;
		}
		
		public void burn(){
			visible = burning;
		}
		
		public void step(){
			visible.step();
		}
		
		public void setNorthwest(){
			visible.sprite.setOrigin(Compass.NORTHWEST);
			if (burning != null)
				burning.sprite.setOrigin(Compass.NORTHWEST);
			render = new Point(x, y);
		}
		
		public void render(Shake s){
			visible.sprite.render(visible.getImage(), render.x + s.x, render.y + s.y, SCALE, SCALE, 0, ColorF.WHITE);
		}
	}
	
	private class Layer{
		public Sprite sprite;
		private double image;
		private boolean animate;
		
		public Layer(String sprite, int image){
			this.sprite = new Sprite(sprite);
			this.image = image;
			animate = false;
		}
		
		public Layer(String sprite){
			this(sprite, 0);
			image = Calc.random(this.sprite.length);
			animate = true;
		}
		
		public void step(){
			if (animate){
				image += .2 + Calc.rangedRandom(.05);
				while(image >= sprite.length)
					image -= sprite.length;
			}
		}
		
		public int getImage(){
			return (int)image;
		}
		
	}

}
